﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Shop.Core.Domain.Customers;
using System.Web;
using Shop.Service.Customers;
using Shop.Service.Security;

namespace Shop.Web.Infrastructure.Customers
{
    public class CustomerContext
    {
        private const string CustomerCookieName = "Shop.Customer";
        private readonly HttpContextBase _httpContext;
        private readonly ICustomerService _customerService;
        private readonly IAuthenticationService _authenticationService;
        private Customer _cachedCustomer;

        public CustomerContext(HttpContextBase httpContext, ICustomerService customerService
            , IAuthenticationService authenticationService)
        {
            this._httpContext = httpContext;
            this._customerService = customerService;
            this._authenticationService = authenticationService;
        }

        protected Customer GetCurrentCustomer()
        {
            if (_cachedCustomer != null)
                return _cachedCustomer;

            Customer customer = null;
            if (_httpContext != null)
            {
                //registered user
                if (customer == null || customer.IsDeleted)
                {
                    customer = _authenticationService.GetAuthenticatedCustomer();
                }

                //load guest customer
                if (customer == null || customer.IsDeleted)
                {
                    HttpCookie customerCookie = GetCustomerCookie();
                    if (customerCookie != null && !String.IsNullOrEmpty(customerCookie.Value))
                    {
                        var customerByCookie = _customerService.GetGuestCustomer(customerCookie.Value);
                        if (customerByCookie != null && !customerByCookie.IsGuest)
                        {
                            customer = customerByCookie;
                        }
                    }
                }

                //create guest if not exists
                if (customer == null || customer.IsDeleted)
                {
                    customer = _customerService.CreateGuestCustomer();
                }
                SetCustomerCookie(customer.NickName);
            }

            //validation
            if (customer != null && !customer.IsDeleted)
            {
                #region
                //update last activity date
                //if (customer.LastActivityDateUtc.AddMinutes(1.0) < DateTime.UtcNow)
                //{
                //    customer.LastActivityDateUtc = DateTime.UtcNow;
                //    _customerService.UpdateCustomer(customer);
                //}

                ////update IP address
                //string currentIpAddress = _webHelper.GetCurrentIpAddress();
                //if (!String.IsNullOrEmpty(currentIpAddress))
                //{
                //    if (!currentIpAddress.Equals(customer.LastIpAddress))
                //    {
                //        customer.LastIpAddress = currentIpAddress;
                //        _customerService.UpdateCustomer(customer);
                //    }
                //}
                #endregion
                _cachedCustomer = customer;
            }

            return _cachedCustomer;
        }

        protected HttpCookie GetCustomerCookie()
        {
            if (_httpContext == null || _httpContext.Request == null)
                return null;

            return _httpContext.Request.Cookies[CustomerCookieName];
        }

        protected void SetCustomerCookie(Guid customerGuid)
        {
            var cookie = new HttpCookie(CustomerCookieName);
            cookie.Value = customerGuid.ToString();
            if (customerGuid == Guid.Empty)
            {
                cookie.Expires = DateTime.UtcNow.AddMonths(-1);
            }
            else
            {
                int cookieExpires = 24 * 365; //TODO make configurable
                cookie.Expires = DateTime.UtcNow.AddHours(cookieExpires);
            }
            if (_httpContext != null && _httpContext.Response != null)
            {
                _httpContext.Response.Cookies.Remove(CustomerCookieName);
                _httpContext.Response.Cookies.Add(cookie);
            }
        }

        /// <summary>
        /// Gets or sets the current customer
        /// </summary>
        public Customer CurrentCustomer
        {
            get
            {
                return GetCurrentCustomer();
            }
            set
            {
                SetCustomerCookie(value.NickName);
                _cachedCustomer = value;
            }
        }

        protected void SetCustomerCookie(string cookieValue)
        {
            var cookie = new HttpCookie(CustomerCookieName);
            if (string.IsNullOrEmpty(cookieValue))
            {
                cookie.Expires = DateTime.UtcNow.AddMonths(-1);
            }
            else
            {
                int cookieExpires = 24 * 365; //TODO make configurable
                cookie.Expires = DateTime.UtcNow.AddHours(cookieExpires);
            }
            if (_httpContext != null && _httpContext.Response != null)
            {
                _httpContext.Response.Cookies.Remove(CustomerCookieName);
                _httpContext.Response.Cookies.Add(cookie);
            }
        }
    }
}
